/**
 * @FilePath     : log_view_model.cpp
 * @Description  : 日志视图模型实现
 */
#include "log_view_model.h"
#include "infrastructure/logging/log_broadcast_sink.h"
#include <QFile>
#include <QTextStream>
#include <QStandardPaths>
#include <QDir>

namespace presentation::viewmodels {

// ==================== SystemLogModel ====================

SystemLogModel::SystemLogModel(QObject* parent)
    : QAbstractListModel(parent)
{
}

int SystemLogModel::rowCount(const QModelIndex& parent) const
{
    if (parent.isValid()) {
        return 0;
    }
    QMutexLocker<QRecursiveMutex> locker(&m_mutex);
    return static_cast<int>(m_entries.size());
}

QVariant SystemLogModel::data(const QModelIndex& index, int role) const
{
    QMutexLocker<QRecursiveMutex> locker(&m_mutex);

    if (!index.isValid() || index.row() < 0 || index.row() >= m_entries.size()) {
        return QVariant();
    }

    const auto& entry = m_entries.at(index.row());

    switch (role) {
        case TimestampRole:
            return entry.timestamp;
        case TimeStringRole:
            return entry.timestamp.toString("HH:mm:ss");
        case LevelRole:
            return entry.level;
        case SourceRole:
            return entry.source;
        case MessageRole:
            return entry.message;
        case FullDateTimeRole:
            return entry.timestamp.toString("yyyy-MM-dd HH:mm:ss.zzz");
        default:
            return QVariant();
    }
}

QHash<int, QByteArray> SystemLogModel::roleNames() const
{
    return {
        {TimestampRole, "timestamp"},
        {TimeStringRole, "timeString"},
        {LevelRole, "level"},
        {SourceRole, "source"},
        {MessageRole, "message"},
        {FullDateTimeRole, "fullDateTime"}
    };
}

void SystemLogModel::addEntry(const QDateTime& timestamp, const QString& level,
                               const QString& source, const QString& message)
{
    // 先检查是否需要删除旧条目
    trimOldEntries();

    QMutexLocker<QRecursiveMutex> locker(&m_mutex);

    const int row = static_cast<int>(m_entries.size());
    beginInsertRows(QModelIndex(), row, row);

    m_entries.append({timestamp, level, source, message});
    updateStats(level, 1);

    endInsertRows();
    locker.unlock();

    emit countChanged();
    emit statsChanged();
    emit entryAdded();
}

void SystemLogModel::clear()
{
    QMutexLocker<QRecursiveMutex> locker(&m_mutex);

    if (m_entries.isEmpty()) {
        return;
    }

    beginResetModel();
    m_entries.clear();
    m_infoCount = 0;
    m_warnCount = 0;
    m_errorCount = 0;
    endResetModel();

    locker.unlock();

    emit countChanged();
    emit statsChanged();
}

QVariantList SystemLogModel::exportLogs() const
{
    QMutexLocker<QRecursiveMutex> locker(&m_mutex);

    QVariantList result;
    result.reserve(m_entries.size());

    for (const auto& entry : m_entries) {
        QVariantMap map;
        map["timestamp"] = entry.timestamp;
        map["timeString"] = entry.timestamp.toString("yyyy-MM-dd HH:mm:ss.zzz");
        map["level"] = entry.level;
        map["source"] = entry.source;
        map["message"] = entry.message;
        result.append(map);
    }

    return result;
}

void SystemLogModel::updateStats(const QString& level, int delta)
{
    if (level == "info") {
        m_infoCount += delta;
    } else if (level == "warn") {
        m_warnCount += delta;
    } else if (level == "error") {
        m_errorCount += delta;
    }
}

void SystemLogModel::trimOldEntries()
{
    QMutexLocker locker(&m_mutex);

    if (m_entries.size() >= m_maxEntries) {
        // 删除最旧的 10% 条目
        const int removeCount = m_maxEntries / 10;
        if (removeCount > 0) {
            beginRemoveRows(QModelIndex(), 0, removeCount - 1);

            // 更新统计
            for (int i = 0; i < removeCount && i < m_entries.size(); ++i) {
                updateStats(m_entries.at(i).level, -1);
            }

            m_entries.remove(0, removeCount);
            endRemoveRows();
        }
    }
}

// ==================== LogFilterProxyModel ====================

LogFilterProxyModel::LogFilterProxyModel(QObject* parent)
    : QSortFilterProxyModel(parent)
{
}

void LogFilterProxyModel::setLevelFilter(const QString& filter)
{
    if (m_levelFilter != filter) {
        m_levelFilter = filter;
        invalidateFilter();
        emit levelFilterChanged();
    }
}

bool LogFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
    if (m_levelFilter == "all") {
        return true;
    }

    QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
    QString level = sourceModel()->data(index, SystemLogModel::LevelRole).toString();

    return level == m_levelFilter;
}

// ==================== LogViewModel ====================

LogViewModel::LogViewModel(QObject* parent)
    : BaseViewModel(parent)
    , m_logModel(std::make_unique<SystemLogModel>(this))
    , m_filteredModel(std::make_unique<LogFilterProxyModel>(this))
{
    m_filteredModel->setSourceModel(m_logModel.get());

    // 连接日志模型的信号
    connect(m_logModel.get(), &SystemLogModel::entryAdded,
            this, &LogViewModel::onEntryAdded);
    connect(m_logModel.get(), &SystemLogModel::statsChanged,
            this, &LogViewModel::statsChanged);
}

LogViewModel::~LogViewModel()
{
    cleanup();
}

void LogViewModel::initialize()
{
    if (isInitialized()) {
        return;
    }

    connectToLogBroadcast();
    BaseViewModel::initialize();
}

void LogViewModel::cleanup()
{
    // 断开与日志广播的连接
    auto* emitter = infrastructure::logging::LogBroadcastEmitter::instance();
    if (emitter) {
        disconnect(emitter, nullptr, this, nullptr);
    }

    BaseViewModel::cleanup();
}

void LogViewModel::setLevelFilter(const QString& filter)
{
    if (m_levelFilter != filter) {
        m_levelFilter = filter;
        m_filteredModel->setLevelFilter(filter);
        emit levelFilterChanged();
    }
}

void LogViewModel::setAutoScroll(bool enabled)
{
    if (m_autoScroll != enabled) {
        m_autoScroll = enabled;
        emit autoScrollChanged();
    }
}

int LogViewModel::totalCount() const
{
    return m_logModel ? m_logModel->count() : 0;
}

int LogViewModel::infoCount() const
{
    return m_logModel ? m_logModel->infoCount() : 0;
}

int LogViewModel::warnCount() const
{
    return m_logModel ? m_logModel->warnCount() : 0;
}

int LogViewModel::errorCount() const
{
    return m_logModel ? m_logModel->errorCount() : 0;
}

void LogViewModel::clearLogs()
{
    if (m_logModel) {
        m_logModel->clear();
    }
}

void LogViewModel::exportToFile(const QString& filePath)
{
    QString path = filePath;

    // 如果未指定路径，使用默认路径
    if (path.isEmpty()) {
        QString docsPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
        QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss");
        path = docsPath + "/AGV_Logs_" + timestamp + ".txt";
    }

    QFile file(path);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        handleError(QString("无法打开文件: %1").arg(path));
        return;
    }

    QTextStream stream(&file);
    stream.setEncoding(QStringConverter::Utf8);

    stream << "AGV 系统日志导出\n";
    stream << "导出时间: " << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss") << "\n";
    stream << "========================================\n\n";

    auto logs = m_logModel->exportLogs();
    for (const auto& log : logs) {
        QVariantMap map = log.toMap();
        stream << QString("[%1] [%2] [%3] %4\n")
                      .arg(map["timeString"].toString())
                      .arg(map["level"].toString().toUpper(), 5)
                      .arg(map["source"].toString())
                      .arg(map["message"].toString());
    }

    file.close();
}

void LogViewModel::setMaxEntries(int max)
{
    if (m_logModel && max > 0) {
        m_logModel->setMaxEntries(max);
    }
}

void LogViewModel::addTestLog(const QString& level, const QString& message)
{
    if (m_logModel) {
        m_logModel->addEntry(QDateTime::currentDateTime(), level, "TestSource", message);
    }
}

void LogViewModel::onLogReceived(const QDateTime& timestamp, const QString& level,
                                  const QString& source, const QString& message)
{
    if (m_logModel) {
        m_logModel->addEntry(timestamp, level, source, message);
    }
}

void LogViewModel::onEntryAdded()
{
    if (m_autoScroll) {
        emit scrollToBottom();
    }
}

void LogViewModel::connectToLogBroadcast()
{
    auto* emitter = infrastructure::logging::LogBroadcastEmitter::instance();
    if (emitter) {
        // 使用 QueuedConnection 确保在主线程处理
        connect(emitter, &infrastructure::logging::LogBroadcastEmitter::logReceived,
                this, &LogViewModel::onLogReceived,
                Qt::QueuedConnection);
    }
}

} // namespace presentation::viewmodels
